package com.lagou.sqlsession;

import com.lagou.pojo.Configuration;
import com.lagou.pojo.MappedStatement;

import java.beans.IntrospectionException;
import java.lang.reflect.*;
import java.sql.SQLException;
import java.util.List;

public class DefaultSqlSession implements SqlSession{

    private final Configuration configuration;

    private final Executor executor;

    private final boolean autoCommit;


    public  DefaultSqlSession(Configuration configuration,Executor executor, boolean autoCommit){
        this.configuration=configuration;
        this.autoCommit = autoCommit;
        this.executor=executor;
    }

    public  DefaultSqlSession(Configuration configuration,Executor executor){
        this(configuration, executor, false);
    }


    public <E> List<E> selecList(String statementid, Object... params) throws SQLException, ClassNotFoundException, InvocationTargetException, IntrospectionException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        //完成Executor里面的query调用
        return executor.query(configuration.getStatementMap().get(statementid),params );
    }

    public <T> T selectOne(String statementid, Object... params) throws SQLException, ClassNotFoundException, IntrospectionException, InstantiationException, IllegalAccessException, NoSuchFieldException, InvocationTargetException {
        List<Object> objects = selecList(statementid, params);
        if(objects.size()==1)
            return  (T)objects.get(0);
        else
            throw new RuntimeException("查询结果为空或存在多条记录");
    }

    @Override
    public int inser(String statementid, Object... params) throws ClassNotFoundException, SQLException, IllegalAccessException, NoSuchFieldException {
        return update(statementid,params);
    }

    public int update(String statementid, Object... params) throws ClassNotFoundException, SQLException, NoSuchFieldException, IllegalAccessException {
        return executor.update(configuration.getStatementMap().get(statementid),params);
    }

    public int delete(String statementid, Object... params) throws ClassNotFoundException, SQLException, IllegalAccessException, NoSuchFieldException {

        return update(statementid,params);
    }

    @Override
    public <T> T getMapper(Class<T> type) {
        Object proxyInstance = Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{type}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                String className = method.getDeclaringClass().getName();//获取类的全称
                String methodName = method.getName();//获取方法名称
                String statementid=className+"."+methodName;
                MappedStatement mappedStatement = configuration.getStatementMap().get(statementid);
                switch (mappedStatement.getSqlCommandType()){
                    case DELETE:
                        return  delete(statementid,args);
                    case INSERT:
                        return  inser(statementid,args);
                    case SELECT:
                        Type type=method.getGenericReturnType();
                        if(type instanceof ParameterizedType)
                            return  selecList(statementid,args);
                        else
                          return   selectOne(statementid,args);
                    case UPDATE:
                        return   update(statementid,args);
                    default:
                        throw  new RuntimeException("找不到对应的sql命令类型");
                }
            }
        });
        return (T) proxyInstance;
    }


    @Override
    public void commit() throws SQLException {
        executor.commit();
    }


    @Override
    public void rollback() throws SQLException {
        executor.rollback();
    }


}
